package com.think.cloud.thinkshop.mall.service.aftersales.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.think.cloud.thinkshop.mall.controller.admin.aftersales.vo.*;
import com.think.cloud.thinkshop.mall.controller.app.payment.dto.RefundDTO;
import com.think.cloud.thinkshop.mall.convert.aftersales.AfterSalesConvert;
import com.think.cloud.thinkshop.mall.domain.aftersales.AfterSales;
import com.think.cloud.thinkshop.mall.domain.aftersales.AfterSalesLog;
import com.think.cloud.thinkshop.mall.domain.order.Order;
import com.think.cloud.thinkshop.mall.domain.websitesetting.WebsiteSetting;
import com.think.cloud.thinkshop.mall.enums.aftersales.AfterSalesStatusEnum;
import com.think.cloud.thinkshop.mall.enums.common.CommonWhetherEnum;
import com.think.cloud.thinkshop.mall.enums.order.OrderDetailStateEnum;
import com.think.cloud.thinkshop.mall.enums.order.OrderOperateUserTypeEnum;
import com.think.cloud.thinkshop.mall.enums.order.OrderStatusEnum;
import com.think.cloud.thinkshop.mall.mapper.aftersales.AfterSalesMapper;
import com.think.cloud.thinkshop.mall.mapper.order.OrderMapper;
import com.think.cloud.thinkshop.mall.service.aftersales.IAfterSalesLogService;
import com.think.cloud.thinkshop.mall.service.aftersales.IAfterSalesService;
import com.think.cloud.thinkshop.mall.service.memberuser.IMemberUserService;
import com.think.cloud.thinkshop.mall.service.order.IOrderDetailService;
import com.think.cloud.thinkshop.mall.service.payment.PaymentService;
import com.think.cloud.thinkshop.mall.service.websitesetting.IWebsiteSettingService;
import com.think.common.core.exception.util.ServiceExceptionUtil;
import com.think.common.core.utils.PageUtils;
import com.think.common.core.web.page.TableDataInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.think.cloud.thinkshop.mall.enums.aftersales.AfterSalesOperateTypeEnum.*;
import static com.think.cloud.thinkshop.mall.enums.aftersales.AfterSalesStatusEnum.*;
import static com.think.cloud.thinkshop.mall.enums.aftersales.AfterSalesTypeEnum.REFUND_ONLY;
import static com.think.common.core.exception.enums.ErrorCode.AFTER_SALES_NOT_EXIST_ERROR;

/**
 * 售后记录Service业务层处理
 *
 * @author zkthink
 * @date 2024-06-12
 */
@Service
public class AfterSalesServiceImpl implements IAfterSalesService {

    @Autowired
    private AfterSalesMapper afterSalesMapper;

    @Autowired
    private IOrderDetailService orderDetailService;

    @Autowired
    private IAfterSalesLogService afterSalesLogService;

    @Autowired
    private IWebsiteSettingService websiteSettingService;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private IMemberUserService memberUserService;

    /**
     * 查询售后记录
     *
     * @param id 售后记录主键
     * @return 售后记录
     */
    @Override
    public AfterSalesInfoRespVO selectAfterSalesById(Long id) {
        AfterSalesInfoRespVO result = AfterSalesConvert.INSTANCE.convert1(getAfterSales(id));
        // 查询订单信息
        Order order = orderMapper.selectById(result.getOrderId());
        result.setOrderCode(order.getOrderCode());
        // 查询订单明细
        List<AfterSalesOrderDetailRespVO> afterSalesDetails =
                orderDetailService.selectOrderDetailListByAfterSalesIds(Arrays.asList(id));
        result.setDetails(afterSalesDetails);
        // 查询操作日志
        List<AfterSalesLogRespVO> afterSalesLogs = afterSalesLogService.selectAfterSalesLogListByAfterSalesId(id);
        result.setLogs(afterSalesLogs);
        return result;
    }

    /**
     * 查询售后记录列表
     *
     * @param vo
     * @return 售后记录
     */
    @Override
    public TableDataInfo selectAfterSalesList(AfterSalesPageReqVO vo) {
        List<AfterSalesPageRespVO> afterSalesList = afterSalesMapper.selectAppAfterSaleList(vo);
        if (CollectionUtil.isNotEmpty(afterSalesList)) {
            List<Long> afterSalesIds = afterSalesList.stream().map(AfterSalesPageRespVO::getId).collect(Collectors.toList());
            // 查询订单明细
            List<AfterSalesOrderDetailRespVO> afterSalesDetails =
                    orderDetailService.selectOrderDetailListByAfterSalesIds(afterSalesIds);
            Map<Long, List<AfterSalesOrderDetailRespVO>> orderDetailMap =
                    afterSalesDetails.stream().collect(Collectors.groupingBy(AfterSalesOrderDetailRespVO::getAfterSalesId));
            afterSalesList.forEach(res -> res.setDetails(orderDetailMap.get(res.getId())));
        }
        return new TableDataInfo(afterSalesList, PageUtils.getTotal(afterSalesList));
    }

    private AfterSales getAfterSales(Long id) {
        AfterSales afterSales = afterSalesMapper.selectById(id);
        if (Objects.isNull(afterSales)) throw ServiceExceptionUtil.exception(AFTER_SALES_NOT_EXIST_ERROR);
        return afterSales;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void audit(AfterSalesAuditReqVO vo) {
        AfterSales afterSales = getAfterSales(vo.getId());
        if (CommonWhetherEnum.NO.getValue().equals(vo.getIsAgree())) {
            commonUpdate(vo.getId(), BUSINESS_REFUSE.getValue(), vo.getUserId());
            return;
        }
        if (AWAITING_AUDIT.getValue().equals(afterSales.getState()) &&
                !REFUND_ONLY.getValue().equals(afterSales.getServiceType())) {
            commonUpdate(vo.getId(), AWAITING_SHIPMENT.getValue(), vo.getUserId());
        } else if (AWAITING_RECEIPT.getValue().equals(afterSales.getState()) ||
                REFUND_ONLY.getValue().equals(afterSales.getServiceType())) {
            commonUpdate(vo.getId(), AGREE_REFUND.getValue(), vo.getUserId());
            refund(afterSales);
        } else {
            throw ServiceExceptionUtil.exception(AFTER_SALES_NOT_EXIST_ERROR);
        }
    }


    /**
     * 通用更新
     *
     * @param id     售后id
     * @param state  售后状态
     * @param userId 登录用户id
     */
    private void commonUpdate(Long id, Integer state, Long userId) {
        AfterSales afterSales = AfterSales.builder().id(id).state(state).build();
        Integer operateType = null;
        switch (AfterSalesStatusEnum.toEnum(state)) {
            case BUSINESS_REFUSE:
                operateType = APPROVAL_FAILED.getValue();
                // 修改订单详情状态
                orderDetailService.updateOrderDetailByAfterSalesId(id, OrderDetailStateEnum.NORMAL.getValue());
                break;
            case AWAITING_SHIPMENT:
                operateType = APPROVAL_SUCCESSFUL.getValue();
                addAddress(afterSales); //存入退货地址信息
                break;
            case AGREE_REFUND:
                operateType = MERCHANT_AGREED_TO_REFUND.getValue();
                break;
            case COMPLETED:
                operateType = REFUND_SUCCESSFUL.getValue();
                // 修改订单详情状态
                orderDetailService.updateOrderDetailByAfterSalesId(id,
                        OrderDetailStateEnum.COMPLETED_AFTER_SALES.getValue());
        }
        // 更新售后单状态
        afterSalesMapper.updateById(afterSales);
        // 存入操作记录
        afterSalesLogService.insertSalesLog(AfterSalesLog.builder().afterSalesId(id)
                .userType(OrderOperateUserTypeEnum.MERCHANT.getValue())
                .userId(userId).operateType(operateType).build());
    }

    private void addAddress(AfterSales afterSales) {
        WebsiteSetting websiteSetting = websiteSettingService.getCache();
        afterSales.setConsignee(websiteSetting.getAddressUsername());
        afterSales.setPhoneNumber(websiteSetting.getAddressPhoneNumber());
        afterSales.setAddress(websiteSetting.getAddressDetails());
        afterSales.setCountry(websiteSetting.getAddressNation());
        afterSales.setPostCode(websiteSetting.getAddressPostcode());
    }

    /**
     * 退款操作
     *
     * @param afterSales
     */
    private void refund(AfterSales afterSales) {
        Order order = orderMapper.selectById(afterSales.getOrderId());
        RefundDTO dto = new RefundDTO();
        dto.setOrderCode(order.getOrderCode());
        dto.setTotal(afterSales.getRefundAmount());
        WebsiteSetting websiteSetting = websiteSettingService.getCache();
        dto.setCurrency(websiteSetting.getCurrencyCode());
        dto.setPaymentIntent(order.getPaymentIntentId());
        dto.setLatestCharge(order.getLatestCharge());
        // 校验退款是否成功
        if (paymentService.createRefund(dto, order.getPayType())) {
            commonUpdate(afterSales.getId(), COMPLETED.getValue(), afterSales.getUserId());
            // 订单全部售后完成
            if (orderDetailService.determineAfterSalesCompleted(order.getId())) {
                orderMapper.updateById(Order.builder().id(order.getId())
                        .status(OrderStatusEnum.REFUNDED.getValue()).build());
            }
            //更新用户退款数据
            memberUserService.updateUserRefundData(afterSales.getUserId(), afterSales.getRefundAmount());
        }
    }
}
